/**
 * 请求封装
 */
import store from '@/store'
import cache from '@/utils/cache'
import errorCode from '@/utils/errorCode'
import axios from 'axios'
import { Message, MessageBox, Loading } from 'element-ui'
import { getPath, blobValidate } from '@/utils/tool.js'
import { saveAs } from 'file-saver'
import { getToken } from '@/utils/token'

// 是否显示重新登录
export const isRelogin = {
    show: false
}

/**
 * 重新登陆
 * @returns
 */
const handleAuthorized = () => {
    if (!isRelogin.show) {
        isRelogin.show = true
        MessageBox.confirm(
            '登录状态已过期，您可以继续留在该页面，或者重新登录',
            '系统提示',
            {
                confirmButtonText: '重新登录',
                cancelButtonText: '取消',
                type: 'warning'
            }
        )
            .then(() => {
                isRelogin.show = false
                store.dispatch('LogOut').then(() => {
                    location.href = getPath('/index')
                })
            })
            .catch(() => {
                isRelogin.show = false
            })
    }
    return Promise.reject('无效的会话，或者会话已过期，请重新登录。')
}

// 加载效果
let downloadLoadingInstance = null
// 访问加载效果
let serverLoadingInstance = null
/**
 * 创建axios实例
 */
const service = axios.create({
    // axios中请求配置有baseURL选项，表示请求URL公共部分
    baseURL: process.env.VUE_APP_BASE_HOST + process.env.VUE_APP_BASE_API,
    // 超时
    timeout: 10000
})

/**
 * 防止重复提交
 */
const repeatSubmit = config => {
    return new Promise((resolve, reject) => {
        try {
            // 是否需要防止数据重复提交
            const isRepeatSubmit = config.headers.repeatSubmit === false
            if (!isRepeatSubmit && config.method === 'post') {
                const requestObj = {
                    url: config.url,
                    data:
                        typeof config.data === 'object'
                            ? JSON.stringify(config.data)
                            : config.data,
                    time: new Date().getTime()
                }
                const sessionObj = cache.session.getJSON('sessionObj')
                if (
                    typeof sessionObj === 'undefined' ||
                    sessionObj === null ||
                    sessionObj === ''
                ) {
                    cache.session.setJSON('sessionObj', requestObj)
                } else {
                    // 请求地址
                    const sUrl = sessionObj.url
                    // 请求数据
                    const sData = sessionObj.data
                    // 请求时间
                    const sTime = sessionObj.time
                    // 间隔时间(ms)，小于此时间视为重复提交
                    const interval = 1000
                    if (
                        sData === requestObj.data &&
                        requestObj.time - sTime < interval &&
                        sUrl === requestObj.url
                    ) {
                        const message = '数据正在处理，请勿重复提交'
                        reject(new Error(message))
                    }
                    cache.session.setJSON('sessionObj', requestObj)
                }
            }
            resolve(config)
        } catch (error) {
            reject(error)
        }
    })
}

/**
 * 请求拦截器
 */
service.interceptors.request.use(
    async config => {
        if (config.loading) {
            serverLoadingInstance = Loading.service({
                background: 'rgba(134,134,134, 1)',
                customClass: 'server-loading'
            })
        }
        // 防止重复提交
        await repeatSubmit(config)
        // 是否需要设置 token
        const isToken = (config.headers || {}).isToken === true
        if (getToken() && !isToken) {
            config.headers['token'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
        }
        // 获取token
        if (!isToken) {
            return config
        }
        return config
    },
    error => {
        Promise.reject(error)
    }
)

/**
 * 响应拦截器
 */
service.interceptors.response.use(
    res => {
        serverLoadingInstance && serverLoadingInstance.close()
        // 未设置状态码则默认成功状态
        const code = res.data.code || 0
        // 获取错误信息
        const msg = errorCode[code] || res.data.msg || errorCode['default']
        // 二进制数据则直接返回
        if (
            res.request.responseType === 'blob' ||
            res.request.responseType === 'arraybuffer'
        ) {
            return res.data
        }
        if (code === 401 || code === 1002) {
            handleAuthorized()
        } else if (code === 500) {
            Message.closeAll()
            Message({
                message: msg,
                type: 'error'
            })
            return Promise.reject(new Error(msg))
        } else if (code !== 0) {
            Message.closeAll()
            Message({
                message: msg,
                type: 'error'
            })
            return Promise.reject('error')
        } else {
            return res.data
        }
    },
    error => {
        let { message } = error
        if (message === 'Network Error') {
            message = '后端接口连接异常'
        } else if (message.includes('timeout')) {
            message = '系统接口请求超时'
        } else if (message.includes('Request failed with status code')) {
            message = `系统接口${message.substr(message.length - 3)}异常`
        }
        Message.closeAll()
        Message({
            message,
            type: 'error',
            duration: 5 * 1000
        })
        return Promise.reject(error)
    }
)

/**
 * 通用下载方法
 * @param {*} url
 * @param {*} params
 * @param {*} filename
 * @returns
 */
export function download(params) {
    downloadLoadingInstance = Loading.service({
        background: 'rgba(134,134,134, 1)',
        customClass: 'server-loading'
    })
    return service
        .post(params.url, params.params, {
            headers: {
                'Content-Type': 'application/json'
            },
            responseType: 'blob'
        })
        .then(async data => {
            const isLogin = await blobValidate(data)
            if (isLogin) {
                let blob = new Blob([data])
                if (data.type.indexOf('sheet') != -1) {
                    blob = new Blob([data], {
                        type: 'application/vnd.ms-excel'
                    })
                }
                saveAs(blob, params.filename)
                downloadLoadingInstance.close()
            } else {
                const resText = await data.text()
                const rspObj = JSON.parse(resText)
                const errMsg =
                    errorCode[rspObj.code] || rspObj.msg || errorCode.default
                Message.error(errMsg)
                downloadLoadingInstance.close()
            }
        })
        .catch(r => {
            Message.error('下载文件出现错误，请联系管理员！')
            downloadLoadingInstance.close()
            throw new Error(r)
        })
}

/**
 * 通用post方法
 * @param {Object} params
 * @returns
 */
export function post(params) {
    return service.post(params.url, params.params, {
        headers: Object.assign(
            {
                // 自定义请求头
                'Content-Type':
                    (params.headers && params.headers.contentType) ||
                    'application/json'
            },
            params.headers
        ),
        // 是否允许重复提交
        isRepeatSubmit: params.isRepeatSubmit || false,
        // 是否有加载效果
        loading: params.loading
    })
}
/**
 * 通用get方法
 * @param {*} params
 * @returns
 */
export function get(params) {
    return service.get(params.url, {
        params: params.params,
        // 自定义请求头
        headers: Object.assign(
            {
                // 自定义请求头
                'Content-Type':
                    (params.headers && params.headers.contentType) ||
                    'application/json'
            },
            params.headers
        ),
        // 是否允许重复提交
        isRepeatSubmit: params.isRepeatSubmit || false,
        // 是否有加载效果
        loading: params.loading
    })
}
